﻿using CSharp.Basic.Learn.EventBus.Events;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace CSharp.Basic.Learn.EventBus.Implement
{
  /// <summary>
  /// 基于内存实现的事件总线
  /// </summary>
  public class InMemoryEventBus : IEventBus
  {

    public static InMemoryEventBus Default { get; } = new InMemoryEventBus();

    #region 事件与事件处理映射字典

    private readonly ConcurrentDictionary<string, List<Type>> _eventToHandlers;

    #endregion

    public InMemoryEventBus()
    {
      _eventToHandlers = new ConcurrentDictionary<string, List<Type>>();
    }


    public void Publish(IntegrationEvent @event)
    {
      // 事件处理类型集合
      var handlerTypes = _eventToHandlers[@event.GetType().Name];
      // 通过反射创建事件处理类型实例
      foreach (var handlerType in handlerTypes)
      {
        MethodInfo methodInfo = handlerType.GetMethod("Handle");
        if (methodInfo != null)
        {
          var obj = Activator.CreateInstance(handlerType);
          methodInfo.Invoke(obj, new object[] { @event });
        }
      }
    }

    public void Publish<TEvent>(TEvent @event) where TEvent : IntegrationEvent
    {
      // 事件处理类型集合
      var key = @event.GetType().Name;
      if (_eventToHandlers.ContainsKey(key))
      {
        var handlerTypes = _eventToHandlers[key];
        // 通过反射创建事件处理类型实例
        foreach (var handlerType in handlerTypes)
        {
          var handler = Activator.CreateInstance(handlerType) as IIntegrationEventHandler<TEvent>;
          handler?.Handle(@event);
        }
      }
    }

    public void Subscribe<T, THandler>()
      where T : IntegrationEvent
      where THandler : IIntegrationEventHandler<T>
    {
      var key = GetEventKey<T>();
      //if (!_eventToHandlers.ContainsKey(key))
      //{
      //  // 字典中没有对应的事件类型
      //  GetOrAddEventHandlers(key).Add(typeof(THandler));
      //}
      //else
      //{
      //  var handlerTypes = _eventToHandlers[key];
      //  // 阻止添加重复的事件处理
      //  if (handlerTypes.Contains(typeof(THandler)))
      //  {
      //    return;
      //  }
      //  handlerTypes.Add(typeof(THandler));
      //  _eventToHandlers[key] = handlerTypes;
      //}
      GetOrAddEventHandlers(key).Add(typeof(THandler));
    }

    private List<Type> GetOrAddEventHandlers(string eventKey)
    {
      return _eventToHandlers.GetOrAdd(eventKey, (key) => new List<Type>());
    }

    public void Unsubscribe<T, THandler>()
      where T : IntegrationEvent
      where THandler : IIntegrationEventHandler<T>
    {
      var key = GetEventKey<T>();
      //if (_eventToHandlers.ContainsKey(key))
      //{
      //  var handlerTypes = _eventToHandlers[key];
      //  handlerTypes.Remove(typeof(THandler));
      //  if (!handlerTypes.Any())
      //  {
      //    //当事件对应的订阅数为0时从字典中删除事件
      //    _eventToHandlers.Remove(key, out List<Type> deleted);
      //  }
      //}
      GetOrAddEventHandlers(key).RemoveAll(m => m == typeof(THandler));
      if (!GetOrAddEventHandlers(key).Any())
      {
        //当事件对应的订阅数为0时从字典中删除事件
        _eventToHandlers.Remove(key, out List<Type> deleted);
      }
    }

    private string GetEventKey<T>()
    {
      return typeof(T).Name;
    }

    public List<Type> UnsubscribeAll<T>() where T : IntegrationEvent
    {
      var key = GetEventKey<T>();
      // TODO: 事件已经在执行了 此时是等待执行完毕后解除事件订阅还是立即停止执行并解除订阅呢
      _eventToHandlers.TryRemove(key, out List<Type> toRemove);
      return toRemove;
    }

  }
}
